package com.yudean.esb.service.handler.impl;

import com.google.common.collect.Lists;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.basic.DateConverter;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.yudean.esb.common.Constants;
import com.yudean.esb.dao.erp.ErpIdsControlDao;
import com.yudean.esb.dao.erp.ErpIdsInvTransactionIntDao;
import com.yudean.esb.domain.erp.ErpIdsControl;
import com.yudean.esb.domain.erp.ErpIdsInvTransactionInt;
import com.yudean.esb.service.handler.ReceiveErpIdsInvTransactionIntService;
import com.yudean.esb.security.SecurtiyChecker;
import com.yudean.esb.util.StringUtil;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;

@Service("receiveErpIdsInvTransactionIntDataServiceImpl")
@Scope("prototype")
public class ReceiveErpIdsInvTransactionIntDataServiceImpl implements ReceiveErpIdsInvTransactionIntService {

    private final static org.slf4j.Logger LOGGER = LoggerFactory.getLogger(ReceiveErpIdsInvTransactionIntDataServiceImpl.class);

    private String errorMsg = "";
    private String errorCode = "";
    private final String servicIDs = "inv_transaction_int";

    //Oracle数据库约束：无法支持1000列以上
    //批量插入，一次批量插入30条数据
    private final int batchSize = 30;

    @Resource
    private SecurtiyChecker securtiyChecker;

    @Resource
    private ErpIdsInvTransactionIntDao erpIdsInvTransactionIntDao;

    @Resource
    private ErpIdsControlDao erpIdsControlDao;


    @Override
    public String putErpIdsInvTransactionIntData(String serviceID,
                                                 String token,
                                                 String transactionID,
                                                 String pkg,
                                                 String totalPackage,
                                                 String rollback,
                                                 String forceReplace,
                                                 String data) {

        LOGGER.info("putErpIdsInvTransactionIntData():request-{serviceID:{},token:{},transationID:{},"
                        + "package:{},totalPackage:{},rollback:{},forceReplace:{},data:{}}",
                serviceID, token, transactionID, pkg, totalPackage, rollback, forceReplace, data);

        if (!validate(serviceID, token)) {
            return errorMsg(serviceID, token, transactionID, errorCode, errorMsg);
        }
        if (data == null || "".equals(data.trim())) {
            return noData(serviceID, token, transactionID);
        }
        long controlId = 0;
        ErpIdsControl erpIdsControl = null;
        try {
            data = java.net.URLDecoder.decode(data, "utf-8");
        } catch (Exception e) {
            LOGGER.info("data URLDecode incorrect,don't need URLDecode");
        } finally {
            if ("inv_transaction_int".equals(serviceID)) {
                try {
                    XStream xstream = new XStream(new DomDriver());
                    //注册日期转换，处理 yyyy-MM-dd HH:mm:ss, yyyy-MM-dd格式日期
                    xstream.registerConverter(new DateConverter("yyyy-MM-dd HH:mm:ss", null, TimeZone.getTimeZone("GMT+8")));
                    xstream.alias("ErpIdsControl", ErpIdsControl.class);
                    xstream.alias("ErpIdsInvTransactionInt", ErpIdsInvTransactionInt.class);
                    List<Object> listData = (List<Object>) xstream.fromXML(data);
                    erpIdsControl = (ErpIdsControl) listData.get(0);
                    controlId = erpIdsControl.getControlId();
                    int listDataCount = listData.size();
                    List<ErpIdsInvTransactionInt> erpIdsInvTransactionIntList = new ArrayList<ErpIdsInvTransactionInt>();
                    for (int i = 1; i < listDataCount; i++) {
                        Object putDataItem = listData.get(i);
                        if (putDataItem instanceof ErpIdsInvTransactionInt) {
                            if (((ErpIdsInvTransactionInt) putDataItem).getControlId() == controlId)
                                erpIdsInvTransactionIntList.add((ErpIdsInvTransactionInt) putDataItem);
                            else {
                                return errorMsg(serviceID, token, transactionID, Constants.CODE_CLIENT_ERROR, "illegal ControlId");
                            }
                        }
                    }
                    if (controlId == -1)
                        return errorMsg(serviceID, token, transactionID, errorCode, errorMsg);
                    //库存数据
                    //分离数组进行批量插入
                    List<List<ErpIdsInvTransactionInt>> listsInSameSize = Lists.partition(erpIdsInvTransactionIntList, batchSize);
                    for (List<ErpIdsInvTransactionInt> item : listsInSameSize) {
                        erpIdsInvTransactionIntDao.batchInsertErpIdsInvTransactionInt(item);
                    }
                    erpIdsControlDao.insertSelective(erpIdsControl);
                } catch (Exception ex) {
                    LOGGER.error("Receive ErpIdsInvTransactionInt Service error Message:{}", ex.getMessage());
                    //推送数据异常，回滚
                    try {
                        if ("inv_transaction_int".equals(serviceID)) {
                            erpIdsInvTransactionIntDao.deleteInvTransactionByControlId(controlId);
                        }
                    } catch (Exception rollbackException) {
                        LOGGER.error("ReceiveErpIdsInvTransactionIntDataServiceImpl  Rollback Error Message:{}", rollbackException.getMessage());
                    }
                    return errorMsg(serviceID, token, transactionID, Constants.CODE_ERROR, ex.getMessage());
                }

                LOGGER.info("erpIdsInvTransactionIntput success :request-{serviceID:{},token:{},data:{}}", serviceID, token, data);
            }
            return wrap2XML(serviceID, token, transactionID, Constants.CODE_SUCCESS, Constants.CODE_SUCCESS_MSG, "1", "1");
        }
    }

    private boolean validate(String serviceID, String token) {
        boolean isValid = true;
        // 验证token
        String[] userInfo = securtiyChecker.getUserInfo(token);

        if (userInfo == null) {
            errorCode = Constants.CODE_AUTH_ERROR;
            errorMsg = "没有访问的权限";
            isValid = false;
        }

        //检查serviceID
        if (StringUtil.isEmpty(serviceID)) {
            errorCode = Constants.CODE_CLIENT_ERROR;
            errorMsg = "serviceID can not be null";
            isValid = false;
        } else {
            if (!servicIDs.contains(serviceID)) {
                errorCode = Constants.CODE_CLIENT_ERROR;
                errorMsg = "illegal serviceID";
                isValid = false;
            }
        }
        return isValid;
    }

    /**
     * 返回错误信息
     *
     * @param serviceID
     * @param token
     * @param transactionID
     * @param result        错误结果
     * @param msg           错误信息详情
     * @return
     */
    private static String errorMsg(String serviceID, String token,
                                   String transactionID, String result, String msg) {
        StringBuilder sb = new StringBuilder();
        LOGGER.info("erpput error :request-{serviceID:{},errorMsg:{}}", serviceID, msg);
        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><service>")
                .append("<serviceID>").append(serviceID).append("</serviceID>")
                .append("<token>").append(token).append("</token>")
                .append("<transactionID>").append(transactionID)
                .append("</transactionID>").append("<result>").append(result)
                .append("</result><msg>").append(msg)
                .append("</msg></service>");
        return sb.toString();
    }

    /**
     * 返回客户端无数据内容
     *
     * @return
     */
    private static String noData(String serviceID, String token, String transactionID) {
        return errorMsg(serviceID, token, transactionID, Constants.CODE_CLIENT_ERROR, "发送无数据内容!");
    }

    private String wrap2XML(String serviceID, String token,
                            String transationID, String result, String msg, String received,
                            String submitted) {
        Document doc = DocumentHelper.createDocument();
        Element serviceElem = doc.addElement("service");
        try {
            Element idElem = serviceElem.addElement("serviceID");
            idElem.addText(serviceID);

            Element tokenElem = serviceElem.addElement("token");
            tokenElem.addText(token);

            Element transtationElem = serviceElem.addElement("transactionID");
            transtationElem.addText(transationID == null ? "" : transationID);

            Element resultElem = serviceElem.addElement("result");
            resultElem.addText(result);

            Element msgElem = serviceElem.addElement("msg");
            msgElem.addText(msg);

            Element receivedElem = serviceElem.addElement("received");
            receivedElem.addText(received);

            Element submittedElem = serviceElem.addElement("submitted");
            submittedElem.addText(submitted);

        } catch (Exception e) {
            LOGGER.error("wrap2XML():e-{}", e.getMessage());
            return errorMsg(serviceID, token, transationID, Constants.CODE_SERVER_ERROR, "生成XML数据内容发生异常！");
        }
        return doc.asXML();
    }
}
